#include <GL/glut.h>
#include "Configuration.h"
#include "Controler.h"
#include "Collection.h"
#include "View.h"
#include "Object.h"
#include "Input.h"
#include "SpaceShip.h"
#include "Enemy.h"
#include "Background.h"
#include "HUD.h"

Controler * Controler::handler = NULL;
bool Controler::Limiter;
int Controler::globalKills;

void Controler::Start(int argc, char **argv)
{
	viewObject = new View();
	Friends = Collection<SpaceShip>(10);
	Enemies = Collection<InteractiveObject>(1000);
	StaticObjects = Collection<BaseObject>(50);
	spawnCounter = 0;
	spawnDelay = 30;
	templateEnemy = Enemy();
	templateEnemy.Initialise("models/enemy1.3ds",Color(0.9,0.2,0.2),Point(Config::TopRightCorner.x+50,0,-150));
	globalKills = 0;
	
	Config::LoadSettings();
	InitializeObjects();
	PlayerInput::LoadKeySettings();
	//glut setup	
	glutInit(&argc,argv);
	viewObject->Initialise(&Friends,&Enemies,&StaticObjects);
	glutSetCursor(GLUT_CURSOR_NONE);
	glutIgnoreKeyRepeat(1);	
	glutKeyboardFunc(PlayerInput::KeyDown);
	glutKeyboardUpFunc(PlayerInput::KeyUp);	
	glutDisplayFunc(&Controler::Action);
	glutIdleFunc(&Controler::Action);
	glutTimerFunc(16,&TimerFunction,0);
	glutMainLoop();
}

void Controler::SpawnEnemies()
{
	if(spawnDelay < 0 && spawnCounter < 300)
	{						
		templateEnemy.SetPosition(Point(Config::TopRightCorner.x+50,-Config::TopRightCorner.y+Config::StageBoarderBottom+rand()%(int)(2*Config::TopRightCorner.y-(Config::StageBoarderBottom+Config::StageBoarderTop)),-150));
		templateEnemy.health = 1+ (int)globalKills/(Config::difficulty*5);
		templateEnemy.attackPower = 1 + (int)globalKills/(Config::difficulty*10);
		Enemies.Add(new Enemy(templateEnemy));		

		if((int)globalKills/Config::difficulty < 300)
			spawnDelay = 150 -(int)globalKills/Config::difficulty;
		else
			spawnDelay = 1;
		spawnCounter++;
	}
	spawnDelay--;
}

void Controler::TimerFunction(int d)
{
	Limiter = false;
	glutTimerFunc(16,&TimerFunction,0);
}

void Controler::Action(void)
{		
	if(Config::LimitFPS && !Limiter)
	{		
		handler->TestForColisions();
		handler->MoveEnemies();
		handler->viewObject->DisplayFrame();
		handler->SpawnEnemies();
		Limiter = true;
	}
	
}

void Controler::MoveEnemies()
{
	for(int i = 0 ; i < Enemies.Count() ; i++)
	{
		if(!Enemies.Get(i)->Move())
		{
			Enemies.RemoveAt(i);
			spawnCounter--;
		}
	}
}

void Controler::TestForColisions()
{
	for(int i = 0 ; i < Friends.Count() ; i++)
	{
		for(int j = 0 ; j < Enemies.Count() ; j++)
		{
			for(int k = 0 ; k < Friends.Get(i)->laser.projectiles.size();k++)
			{
				if(Friends.Get(i)->laser.projectiles[k].HitTest(Enemies.Get(j)))
				{					
					Friends.Get(i)->laser.projectiles[k].IsAlive = false;
					Enemies.Get(j)->health -= Friends.Get(i)->laser.projectiles[k].power;
					if(Enemies.Get(j)->health <= 0)
					{
						Enemies.Get(j)->IsAlive = false;
						Friends.Get(i)->Kills++;
						globalKills++;
					}
				}
			}
			if(Friends.Get(i)->HitTest(Enemies.Get(j)))
			{
				Enemies.Get(j)->IsAlive = false;
				Friends.Get(i)->health -= Enemies.Get(j)->attackPower;
				if(Friends.Get(i)->health <=0)
				{
					HUD::ShowEndScreen();
					Friends.Get(i)->IsAlive = false;
					globalKills++;
				}
			}
		}
	}
}


void Controler::InitializeObjects()
{


	Friends.Add(new SpaceShip());
	Friends.Get(Friends.Count()-1)->Initialise("models/ship.3ds");
	//adding HUD
	StaticObjects.Add(new HUD(&Friends.Get(Friends.Count()-1)->health,&Friends.Get(Friends.Count()-1)->Kills));
	StaticObjects.Add(new Background());
	StaticObjects.Get(StaticObjects.Count()-1)->Initialise();
}